module fn.adt.graph.Digraph


open QuickGraph



type BidirectionalGraph<'TVertex, 'TEdge when 'TVertex :> obj and 'TEdge :> IEdge<'TVertex>> with

    static member fromVE (e : Edge<'TVertex> -> 'TEdge) V E =
        let g = BidirectionalGraph<'TVertex, 'TEdge>()
        do
            for v in V do g.AddVertex(v) |> ignore
            for (u,v) in E do g.AddEdge(e(Edge(u,v))) |> ignore
        g

    static member fromVE' (e : Edge<'TVertex> -> 'TEdge) V E =
        let g = BidirectionalGraph<'TVertex, 'TEdge>()
        do
            for v in V do g.AddVertex(v) |> ignore
            for (u,v,x) in E do
                g.AddEdge(
                    match x with
                    | Some tag -> e(TaggedEdge(u,v,tag))
                    | None -> e(Edge(u,v))) |> ignore
        g

    member this.merge (other : BidirectionalGraph<'TVertex, 'TEdge>) =
        let vc = this.AddVertexRange other.Vertices
        let ec =this.AddVerticesAndEdgeRange other.Edges
        vc > 0 || ec > 0



let digraph_of_obj<'a when 'a :> obj> (V : 'a list) (E : ('a * 'a) list)  =
    let V', E' = [for v in V -> v:>obj],  [for u,v in E -> u:>obj,v:>obj]
    BidirectionalGraph<obj, IEdge<obj>>.fromVE (fun e -> e :> IEdge<obj>) V' E'
